home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / objam01.lha / objam / objc / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-11  |  7.3 KB  |  256 lines

  1. /*
  2. ** ObjectiveAmiga: Objective C Runtime initialization 
  3. ** See GNU:lib/libobjam/ReadMe for details
  4. */
  5.  
  6.  
  7. #include "runtime.h"
  8.  
  9. /* The version number of this runtime.  This must match the number 
  10.    defined in gcc (objc-act.c) */
  11. #define OBJC_VERSION 5
  12. #define PROTOCOL_VERSION 2
  13.  
  14. /* This list contains all modules currently loaded into the runtime */
  15. static struct objc_list* __objc_module_list = 0;
  16.  
  17. /* This list contains all proto_list's not yet assigned class links */
  18. static struct objc_list* unclaimed_proto_list = 0;
  19.  
  20. /* Check compiler vs runtime version */
  21. static void init_check_module_version(Module_t);
  22.  
  23. /* Assign isa links to protos */
  24. static void __objc_init_protocols (struct objc_protocol_list* protos);
  25.  
  26. /* Add protocol to class */
  27. static void __objc_class_add_protocols (OCClass*, struct objc_protocol_list*);
  28.  
  29. /* Is all categories/classes resolved? */
  30. BOOL __objc_dangling_categories = NO;
  31.  
  32. /* This function is called by constructor functions generated for each
  33.    module compiled.  (_GLOBAL_$I$...) The purpose of this function is to
  34.    gather the module pointers so that they may be processed by the
  35.    initialization routines as soon as possible */
  36.  
  37. void
  38. __objc_exec_class (Module_t module)
  39. {
  40.   /* Has we processed any constructors previously?  This flag used to 
  41.      indicate that some global data structures need to be built.  */ 
  42.   static BOOL previous_constructors = 0;
  43.  
  44.   static struct objc_list* unclaimed_categories = 0;
  45.  
  46.   /* The symbol table (defined in objc.h) generated by gcc */
  47.   Symtab_t symtab = module->symtab;
  48.  
  49.   /* Entry used to traverse hash lists */
  50.   struct objc_list** cell;
  51.  
  52.   /* The table of selector references for this module */
  53.   SEL *selectors = symtab->refs; 
  54.  
  55.   /* dummy counter */
  56.   int i;
  57.  
  58.   DEBUG_PRINTF ("received module: %s\n", module->name);
  59.   /* check gcc version */
  60.   init_check_module_version(module);
  61.  
  62.   /* On the first call of this routine, initialize some data structures.  */
  63.   if (!previous_constructors)
  64.     {
  65.       __objc_init_selector_tables();
  66.       __objc_init_class_tables();
  67.       __objc_init_dispatch_tables();
  68.       previous_constructors = 1;
  69.     }
  70.  
  71.   /* Save the module pointer for later processing. (not currently used) */
  72.   __objc_module_list = list_cons(module, __objc_module_list);
  73.  
  74.   /* Parse the classes in the load module and gather selector information.  */
  75.   DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
  76.   for (i = 0; i < symtab->cls_def_cnt; ++i)
  77.     {
  78.       OCClass* class = (OCClass*) symtab->defs[i];
  79.  
  80.       /* Make sure we have what we think.  */
  81.       assert (CLS_ISCLASS(class));
  82.       assert (CLS_ISMETA(class->class_pointer));
  83.       DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
  84.  
  85.       /* Store the class in the class table and assign class numbers.  */
  86.       __objc_add_class_to_hash (class);
  87.  
  88.       /* Register all of the selectors in the class and meta class.  */
  89.       __objc_register_selectors_from_class (class);
  90.       __objc_register_selectors_from_class ((OCClass*) class->class_pointer);
  91.  
  92.       /* Install the fake dispatch tables */
  93.       __objc_install_premature_dtable(class);
  94.       __objc_install_premature_dtable(class->class_pointer);
  95.  
  96.       if (class->protocols)
  97.     __objc_init_protocols (class->protocols);
  98.    }
  99.  
  100.   /* Replace referenced selectors from names to SEL's.  */
  101.   if (selectors)
  102.     {
  103.       for (i = 0; selectors[i]; ++i)
  104.     selectors[i] = sel_register_name ((const char *) selectors[i]);
  105.     }
  106.  
  107.   /* Process category information from the module.  */
  108.   for (i = 0; i < symtab->cat_def_cnt; ++i)
  109.     {
  110.       Category_t category = symtab->defs[i + symtab->cls_def_cnt];
  111.       OCClass* class = objc_lookup_class (category->class_name);
  112.       
  113.       /* If the class for the category exists then append its methods.  */
  114.       if (class)
  115.     {
  116.  
  117.       DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
  118.             module->name,
  119.             class->name);
  120.  
  121.       /* Do instance methods.  */
  122.       if (category->instance_methods)
  123.         class_add_method_list (class, category->instance_methods);
  124.  
  125.       /* Do class methods.  */
  126.       if (category->class_methods)
  127.         class_add_method_list ((OCClass*) class->class_pointer, 
  128.                    category->class_methods);
  129.  
  130.       if (category->protocols)
  131.         {
  132.           __objc_init_protocols (category->protocols);
  133.           __objc_class_add_protocols (class, category->protocols);
  134.         }
  135.  
  136.     }
  137.       else
  138.     {
  139.       /* The object to which the category methods belong can't be found.
  140.          Save the information.  */
  141.       unclaimed_categories = list_cons(category, unclaimed_categories);
  142.     }
  143.     }
  144.  
  145.   /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
  146.      categories to objects.  */
  147.   for (cell = &unclaimed_categories;
  148.        *cell;
  149.        *cell && ((cell = &(*cell)->tail)))
  150.     {
  151.       Category_t category = (*cell)->head;
  152.       OCClass* class = objc_lookup_class (category->class_name);
  153.       
  154.       if (class)
  155.     {
  156.       DEBUG_PRINTF ("attaching stored categories to object: %s\n",
  157.             class->name);
  158.       
  159.       list_remove_head (cell);
  160.       
  161.       if (category->instance_methods)
  162.         class_add_method_list (class, category->instance_methods);
  163.       
  164.       if (category->class_methods)
  165.         class_add_method_list ((OCClass*) class->class_pointer,
  166.                    category->class_methods);
  167.       
  168.       if (category->protocols)
  169.         {
  170.           __objc_init_protocols (category->protocols);
  171.           __objc_class_add_protocols (class, category->protocols);
  172.         }
  173.       
  174.     }
  175.     }
  176.   
  177.   if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
  178.     {
  179.       list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
  180.       list_free (unclaimed_proto_list);
  181.       unclaimed_proto_list = 0;
  182.     }
  183.  
  184. }
  185.  
  186. /* Sanity check the version of gcc used to compile `module'*/
  187. static void init_check_module_version(Module_t module)
  188. {
  189.   if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
  190.     {
  191.       fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
  192.            module->name, module->version, OBJC_VERSION);
  193.       if(module->version > OBJC_VERSION)
  194.     fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
  195.       else if (module->version < OBJC_VERSION)
  196.     fprintf (stderr, "Compiler (gcc) is out of date\n");
  197.       else
  198.     fprintf (stderr, "Objective C internal error -- bad Module size\n");
  199.       abort ();
  200.     }
  201. }
  202.  
  203. static void
  204. __objc_init_protocols (struct objc_protocol_list* protos)
  205. {
  206.   int i;
  207.   static OCClass* proto_class = 0;
  208.  
  209.   if (! protos)
  210.     return;
  211.  
  212.   if (!proto_class)
  213.     proto_class = objc_lookup_class("Protocol");
  214.  
  215.   if (!proto_class)
  216.     {
  217.       unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
  218.       return;
  219.     }
  220.  
  221.   assert (protos->next == 0);    /* only single ones allowed */
  222.  
  223.   for(i = 0; i < protos->count; i++)
  224.     {
  225.       struct objc_protocol* aProto = protos->list[i];
  226.       if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
  227.     {
  228.       /* assign class pointer */
  229.       aProto->class_pointer = proto_class;
  230.  
  231.       /* init super protocols */
  232.       __objc_init_protocols (aProto->protocol_list);
  233.     }
  234.       else if (protos->list[i]->class_pointer != proto_class)
  235.     {
  236.       fprintf (stderr,
  237.            "Version %d doesn't match runtime protocol version %d\n",
  238.            ((size_t)protos->list[i]->class_pointer),
  239.            PROTOCOL_VERSION);
  240.       abort ();
  241.     }
  242.     }
  243. }
  244.  
  245. static void __objc_class_add_protocols (OCClass* class,
  246.                     struct objc_protocol_list* protos)
  247. {
  248.   /* Well... */
  249.   if (! protos)
  250.     return;
  251.  
  252.   /* Add it... */
  253.   protos->next = class->protocols;
  254.   class->protocols = protos;
  255. }
  256.